package com.yuanqi.service.impl;

import com.yuanqi.domain.AccountsPayableNew;
import com.yuanqi.repository.AccountsPayableNewRepository;
import com.yuanqi.service.AccountsPayableNewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class AccountsPayableNewServiceImpl implements AccountsPayableNewService {
    
    @Autowired
    private AccountsPayableNewRepository accountsPayableNewRepository;
    
    @Override
    public Page<AccountsPayableNew> getAccountsPayablePage(
            String supplierName, 
            Integer overdueStatus, 
            LocalDate dueDate, 
            Pageable pageable) {
        
        // 处理搜索条件
        String searchSupplierName = (supplierName != null && !supplierName.trim().isEmpty()) ? supplierName.trim() : null;
        Integer searchOverdueStatus = (overdueStatus != null && overdueStatus >= 0) ? overdueStatus : null;
        LocalDate searchDueDate = dueDate;
        
        return accountsPayableNewRepository.findBySearchCriteria(
            searchSupplierName, 
            searchOverdueStatus, 
            searchDueDate, 
            pageable
        );
    }
    
    @Override
    public AccountsPayableNew getById(Long id) {
        return accountsPayableNewRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("应付账款不存在，ID: " + id));
    }
    
    @Override
    public List<AccountsPayableNew> getBySupplierId(Long supplierId) {
        return accountsPayableNewRepository.findBySupplierId(supplierId);
    }
    
    @Override
    public List<AccountsPayableNew> getOverdueAccounts() {
        return accountsPayableNewRepository.findByOverdueStatus(1);
    }
    
    @Override
    public AccountsPayableNew create(AccountsPayableNew accountsPayable) {
        accountsPayable.setCreateTime(LocalDateTime.now());
        accountsPayable.setUpdateTime(LocalDateTime.now());
        
        // 计算未付金额
        if (accountsPayable.getTotalAmount() != null && accountsPayable.getPaidAmount() != null) {
            accountsPayable.setUnpaidAmount(
                accountsPayable.getTotalAmount().subtract(accountsPayable.getPaidAmount())
            );
        }
        
        // 检查是否逾期
        if (accountsPayable.getDueDate() != null && accountsPayable.getUnpaidAmount() != null) {
            if (LocalDate.now().isAfter(accountsPayable.getDueDate()) && 
                accountsPayable.getUnpaidAmount().compareTo(BigDecimal.ZERO) > 0) {
                accountsPayable.setOverdueStatus(1);
                accountsPayable.setOverdueDays((int) (LocalDate.now().toEpochDay() - accountsPayable.getDueDate().toEpochDay()));
            } else {
                accountsPayable.setOverdueStatus(0);
                accountsPayable.setOverdueDays(0);
            }
        }
        
        return accountsPayableNewRepository.save(accountsPayable);
    }
    
    @Override
    public AccountsPayableNew update(Long id, AccountsPayableNew accountsPayableDetails) {
        return accountsPayableNewRepository.findById(id)
                .map(existing -> {
                    // 更新字段
                    if (accountsPayableDetails.getSupplierName() != null) {
                        existing.setSupplierName(accountsPayableDetails.getSupplierName());
                    }
                    if (accountsPayableDetails.getTotalAmount() != null) {
                        existing.setTotalAmount(accountsPayableDetails.getTotalAmount());
                    }
                    if (accountsPayableDetails.getPaidAmount() != null) {
                        existing.setPaidAmount(accountsPayableDetails.getPaidAmount());
                    }
                    if (accountsPayableDetails.getDueDate() != null) {
                        existing.setDueDate(accountsPayableDetails.getDueDate());
                    }
                    if (accountsPayableDetails.getRemark() != null) {
                        existing.setRemark(accountsPayableDetails.getRemark());
                    }
                    
                    // 重新计算未付金额
                    if (existing.getTotalAmount() != null && existing.getPaidAmount() != null) {
                        existing.setUnpaidAmount(
                            existing.getTotalAmount().subtract(existing.getPaidAmount())
                        );
                    }
                    
                    // 重新检查逾期状态
                    if (existing.getDueDate() != null && existing.getUnpaidAmount() != null) {
                        if (LocalDate.now().isAfter(existing.getDueDate()) && 
                            existing.getUnpaidAmount().compareTo(BigDecimal.ZERO) > 0) {
                            existing.setOverdueStatus(1);
                            existing.setOverdueDays((int) (LocalDate.now().toEpochDay() - existing.getDueDate().toEpochDay()));
                        } else {
                            existing.setOverdueStatus(0);
                            existing.setOverdueDays(0);
                        }
                    }
                    
                    existing.setUpdateTime(LocalDateTime.now());
                    return accountsPayableNewRepository.save(existing);
                })
                .orElseThrow(() -> new RuntimeException("应付账款不存在，ID: " + id));
    }
    
    @Override
    public void delete(Long id) {
        if (!accountsPayableNewRepository.existsById(id)) {
            throw new RuntimeException("应付账款不存在，ID: " + id);
        }
        accountsPayableNewRepository.deleteById(id);
    }
    
    @Override
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        
        stats.put("totalPayable", getTotalPayableAmount());
        stats.put("totalPaid", getTotalPaidAmount());
        stats.put("totalUnpaid", getTotalUnpaidAmount());
        stats.put("totalOverdue", getTotalOverdueAmount());
        stats.put("supplierCount", getSupplierCount());
        stats.put("thisMonthPayment", getThisMonthPaymentAmount());
        
        return stats;
    }
    
    @Override
    public BigDecimal getTotalPayableAmount() {
        return accountsPayableNewRepository.getTotalPayableAmount();
    }
    
    @Override
    public BigDecimal getTotalPaidAmount() {
        return accountsPayableNewRepository.getTotalPaidAmount();
    }
    
    @Override
    public BigDecimal getTotalUnpaidAmount() {
        return accountsPayableNewRepository.getTotalUnpaidAmount();
    }
    
    @Override
    public BigDecimal getTotalOverdueAmount() {
        return accountsPayableNewRepository.getTotalOverdueAmount();
    }
    
    @Override
    public Long getSupplierCount() {
        return accountsPayableNewRepository.getSupplierCount();
    }
    
    @Override
    public BigDecimal getThisMonthPaymentAmount() {
        return accountsPayableNewRepository.getThisMonthPaymentAmount();
    }
}
